/*
 * 作者：Peter Xiang
 * 联系方式：565067150@qq.com
 * 文档: https://github.com/PxGame
 * 创建时间: 2019/10/28 16:10:56
 */

using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using XMLib.Extensions;
using ActionSystem.Core;
using System.Reflection;
using System.IO;

namespace XMLib.AM
{

    /// <summary>
    /// ActionEditorWindow：工具的主窗口
    /// </summary>
    public class BoxConflictEditorWindow : EditorWindow
    {
        [MenuItem("动作编辑器/碰撞检测设置")]
        public static void ShowEditor()
        {
            EditorWindow.GetWindow<BoxConflictEditorWindow>();            
        }
        TextAsset configAsset;
        ActionSystemBoxConflictConfig config;
        public BoxConflictEditorWindow()
        {
            this.titleContent = new GUIContent("碰撞检测设置");
        }
        ~BoxConflictEditorWindow()
        {
        }

        /// <summary>
        /// 销毁
        /// </summary>
        private void OnDestroy()
        {
            //销毁所有子窗口
        }
        private void OnEnable()
        {
            for(int i=0;i< ActionSystemConstDefine.MaxLayer + 1;i++)
            {
                layerValues[i] = i;
            }
            if (configAsset != null)
            {
                UpdateConfig(configAsset);
            }
        }
        /// <summary>
        /// 绘制
        /// </summary>
        private void OnGUI()
        {
            //
            EditorMode();


            Repaint();
        }
        int matrixIndex = 0;
        int priorityIndex = 0;
        static int[] layerValues = new int[ActionSystemConstDefine.MaxLayer + 1];
        static string[] layerNames = new string[ActionSystemConstDefine.MaxLayer+1];
        private void EditorMode()
        {
            Event evt = Event.current;
            EditorGUILayout.BeginVertical();
            EditorGUILayout.BeginHorizontal();
            //创建配置文件
            if (GUILayout.Button("创建", GUILayout.Width(80)))
            {
                GUI.FocusControl(null);
                CreateNew();
            }
            

            //GUILayout.FlexibleSpace();
            
            //配置文件
            EditorGUI.BeginChangeCheck();
            configAsset = (TextAsset)EditorGUILayout.ObjectField(configAsset, typeof(TextAsset), false);
            if (EditorGUI.EndChangeCheck())
            {
                if (configAsset != null)
                {
                    UpdateConfig(configAsset);
                }
            }
            if (GUILayout.Button("保存", GUILayout.Width(80)))
            {
                GUI.FocusControl(null);
                //保存
                SaveConfig();
            }
            EditorGUILayout.EndHorizontal();
            if(isConfigValid)
            {
                
                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.BeginVertical();
                GUILayout.Label("碰撞交互设置:", GUILayout.MaxWidth(EditorGUILayoutEx.CalcLabelWidth("碰撞交互设置:")));
                matrixIndex = EditorGUILayoutEx.DrawList(config.matrix, matrixIndex, ref scrollPos, NewConflict, BoxConflictDrawer);
                EditorGUILayout.EndVertical();
                GUILayout.Box("",GUILayout.MaxHeight(99999999));
                EditorGUILayout.BeginVertical();
                GUILayout.Label("碰撞响应优先级:", GUILayout.MaxWidth(EditorGUILayoutEx.CalcLabelWidth("碰撞响应优先级:")));
                priorityIndex = EditorGUILayoutEx.DrawList(config.priorities, priorityIndex, ref scrollPos, NewPriority, BoxConflictPriorityDrawer);
                EditorGUILayout.EndVertical();
                EditorGUILayout.EndHorizontal();
                

            }
            

            EditorGUILayout.EndVertical();
        }
        private void NewConflict(Action<BoxConflictConfig> adder)
        {
            var newConflict = new BoxConflictConfig();
            adder(newConflict);
        }
        private void NewPriority(Action<BoxConflictPairPriority> adder)
        {
            var newConflict = new BoxConflictPairPriority();
            adder(newConflict);
        }
        public static void BoxConflictDrawer(int index, ref bool selected, BoxConflictConfig obj)
        {
            if (GUILayout.Button($"{index}", selected ? AEStyles.item_head_select : AEStyles.item_head_normal, GUILayout.ExpandHeight(true), GUILayout.Width(15)))
            {
                GUI.FocusControl(null);
                selected = !selected;
            }
            GUILayout.BeginHorizontal();            
            {
                bool hasDraw = false;
                //获取到定义的名称
                var names = TypeCache.GetTypesWithAttribute<BoxTypeNameAttribute>();
                if (names.Count > 0)
                {
                    Type boxTypeName = names[0];
                    var values = Enum.GetValues(boxTypeName) as int[];
                    var displayNames = Enum.GetNames(boxTypeName);
                    GUILayout.Label("攻击类型:", GUILayout.MaxWidth(EditorGUILayoutEx.CalcLabelWidth("攻击类型:")));
                    obj.boxType = EditorGUILayout.IntPopup(obj.boxType, displayNames, values, GUILayout.MaxWidth(150));

                    GUILayout.Label("Unity Layer:", GUILayout.MaxWidth(EditorGUILayoutEx.CalcLabelWidth("Unity Layer:")));
                    for(int i=0;i< ActionSystemConstDefine.MaxLayer + 1; i++)
                    {
                        layerNames[i] = $"{i}:{LayerMask.LayerToName(i)}";
                    }

                    obj.unityLayer = EditorGUILayout.IntPopup(obj.unityLayer, layerNames, layerValues, GUILayout.MaxWidth(100));


                    GUILayout.Label("碰撞:", GUILayout.MaxWidth(EditorGUILayoutEx.CalcLabelWidth("碰撞:")));
                    int mask = 0;
                    for(int i=0;i<values.Length;i++)
                    {
                        if((obj.boxMask&(1<<values[i]))!=0)
                        {
                            mask |= 1 << i;
                        }
                    }
                    for(int i=0;i<values.Length;i++)
                    {
                        GUILayout.Label(displayNames[i], GUILayout.MaxWidth(EditorGUILayoutEx.CalcLabelWidth(displayNames[i])));
                        if (EditorGUILayout.Toggle((mask & (1 << i)) != 0,GUILayout.MaxWidth(14)))
                        {
                            mask |= 1 << i;
                        }else
                        {
                            mask &= ~(1 << i);
                        }
                    }
                    GUILayout.Label("  ", GUILayout.MaxWidth(EditorGUILayoutEx.CalcLabelWidth("  ")));
                    mask = EditorGUILayout.MaskField(mask, displayNames);
                    obj.boxMask = 0;
                    for (int i = 0; i < values.Length; i++)
                    {
                        if((mask&(1<<i))!=0)
                        {
                            obj.boxMask |= 1<<values[i];
                        }
                    }
                    hasDraw = true;
                }
                if (hasDraw == false)
                {
                    obj.boxType = EditorGUILayoutEx.DrawObject("攻击类型:", obj.boxType);
                    obj.unityLayer = EditorGUILayoutEx.DrawObject("Unity Layer:", obj.unityLayer);
                    obj.boxMask = EditorGUILayoutEx.DrawObject("碰撞:",obj.boxMask);
                }
                obj.boxType = Mathf.Clamp(obj.boxType, 0, ActionSystemConstDefine.MaxLayer + 1);
                obj.unityLayer = Mathf.Clamp(obj.unityLayer, 0, ActionSystemConstDefine.MaxLayer + 1);
            }
            GUILayout.EndVertical();
        }
        public static void BoxConflictPriorityDrawer(int index, ref bool selected, BoxConflictPairPriority obj)
        {
            if (GUILayout.Button($"{index}", selected ? AEStyles.item_head_select : AEStyles.item_head_normal, GUILayout.ExpandHeight(true), GUILayout.Width(15)))
            {
                GUI.FocusControl(null);
                selected = !selected;
            }
            GUILayout.BeginHorizontal();
            {
                bool hasDraw = false;
                //获取到定义的名称
                var names = TypeCache.GetTypesWithAttribute<BoxTypeNameAttribute>();
                if (names.Count > 0)
                {
                    Type boxTypeName = names[0];
                    var values = Enum.GetValues(boxTypeName) as int[];
                    var displayNames = Enum.GetNames(boxTypeName);
                    GUILayout.Label("攻击类型:", GUILayout.MaxWidth(EditorGUILayoutEx.CalcLabelWidth("攻击类型:")));
                    obj.attackingType = EditorGUILayout.IntPopup(obj.attackingType, displayNames, values, GUILayout.MaxWidth(150));
                    GUILayout.Label("受击类型:", GUILayout.MaxWidth(EditorGUILayoutEx.CalcLabelWidth("受击类型:")));
                    obj.attackedType = EditorGUILayout.IntPopup(obj.attackedType, displayNames, values, GUILayout.MaxWidth(150));
                    GUILayout.Label("处理优先级:", GUILayout.MaxWidth(EditorGUILayoutEx.CalcLabelWidth("处理优先级:")));
                    obj.priority = EditorGUILayout.IntField(obj.priority);
                }
            }
            GUILayout.EndVertical();
        }
        bool isConfigValid=> config != null && (configAsset != null);
        private Vector2 scrollPos;
        private Vector2 scrollPos2;
        public void SaveConfig()
        {
            if (!isConfigValid)
            {
                throw new RuntimeException($"未选择配置资源");
            }

            string path = AssetDatabase.GetAssetPath(configAsset);
            string data = DataUtility.ToJson(config);
            //数据保存
            File.WriteAllText(path, data);
            Debug.Log($"当前配置已保存 : {path}");
            AssetDatabase.Refresh();
        }        
        private void CreateNew()
        {
            //获取选中的文件夹
            string dir = EditorUtilityEx.GetSelectDirectory();
            //检测文件路径是否合法
            string filePath = EditorUtilityEx.ValidFilePath(Path.Combine(dir, "BoxConflictConfig.bytes"));
            //创建空文件
            string data = DataUtility.ToJson(new ActionSystemBoxConflictConfig());
            File.WriteAllText(filePath, data);
            Debug.Log($"配置已创建到 : {filePath}");
            AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
            configAsset = AssetDatabase.LoadAssetAtPath<TextAsset>(filePath);
            UpdateConfig(configAsset);
        }

        public void UpdateConfig(TextAsset config)
        {
            if (config == null)
            {
                throw new RuntimeException($"未选择配置资源");
            }

            this.configAsset = config;
            this.config = DataUtility.FromJson<ActionSystemBoxConflictConfig>(config.text);
            if (this.config == null)
            {
                throw new RuntimeException($"配置资源解析失败");
            }

        }
    }
}